/**
*
*  中级应用的客户端
*
**/
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<errno.h>
#include<unistd.h>

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#include<event.h>
#include<event2/bufferevent.h>
#include<event2/buffer.h>
#include<event2/util.h>

void cmd_msg_cb(int fd, short events, void *arg);
void server_msg_cb(struct bufferevent* , void* arg);
void event_cb(struct bufferevent *bev , short events , void *arg);

int main()
{
    int sockfd , status;
    struct  sockaddr_in  server_addr;

    memset(&server_addr ,0 , sizeof(server_addr) );
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(65533);
    inet_aton("127.0.0.1" , &server_addr.sin_addr);
    sockfd = socket(PF_INET , SOCK_STREAM , 0);

    status = connect(sockfd,(sockaddr *)&server_addr , sizeof(server_addr) );
    evutil_make_socket_nonblocking(sockfd);

    struct event_base *base  = event_base_new();
    struct bufferevent *bev  = bufferevent_socket_new();
    struct event *ev_cmd = event_new(base , STDIN_FILENO ,EV_READ | EV_PERSIST ,cmd_msg_cb, (void *)dev);
    event_add(ev_cmd , NULL);
    bufferevent_setcb(bev , server_msg_cb , NULL, event_cb , (void*)ev_cmd );
    bufferevent_enable(bev , EV_READ |EV_PERSIST);
    event_base_dispatch(base);

}

void cmd_msg_cb(int fd, short events, void *arg)
{
    char msg[1024];
    int ret = read(fd , msg ,sizeof(msg));
    struct bufferevent *bev = (struct bufferevent *)arg;
    bufferevent_write(bev , msg, ret);
}

void server_msg_cb(bufferevent * bev, void *arg)
{
    char msg[1024];
    size_t len = bufferevent_read(bev , msg, sizeof(msg));
    msg[len] = '\0';
    printf(" recv %s form server \n ", msg);
}

void event_cb(bufferevent *bev, short events, void *arg)
{
    if(events & BEV_EVENT_EOF)
        printf( " connect closed \n");
    else if(events & BEV_EVENT_ERROR)
        printf("  some other error \n");
    else if(events & BEV_EVENT_CONNECTED)
    {

        printf(" the client has connected to server \n");
        return ;
    }
    bufferevent_free(bev);
    struct event *ev =(struct event*)arg;
    event_free(ev);
}

